vue+element 实现 试卷答题功能,单选题 ,多选题,判断题,简答题(2.0版本,2021.3.25更新)
文章目录
vue+element 实现 试卷答题功能,单选题 ,多选题,判断题,简答题(2.0版本,2021.3.25更新)难点:一、后端返回数据()方法一页面1.html2.js - 答题部分3.js - 回显部分
方法二:1.html2.js - 答题部分3.js - 回显部分
总结方法一优点:可以使用表单的任何属性,使用方便方法一缺点:数据结构有点麻烦,然后提交函数最好封装一下方法二优点:没有报错,不用搞那么多乱七八糟的函数,看着省心,用着及其方便方法二缺点:表单验证什么的.......你懂得
难点:
如何循环不同类型的题如何记录点击的是哪道题,并且分清楚他是单选还是多选单选还好,多选的话不能出现点了一道题,其他题的答案都是点击的这个选项回显的时候如何再把值赋上去附加功能:设置开始时间和结束时间,未到时间不可答题(后端做判断),到时间后自动提交
要和后端商量,把所有时间搞成秒,这样好判断时间到没到,分钟的话太大,毫秒的话,不可能那么精确,而且脸黑的话,两个毫秒值永远不可能相等
ps: 一定要看注释
一、后端返回数据()
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201216173216304.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzEyMzk1,size_16,color_FFFFFF,t_70)
{
"returnObject": {
"count": 380,
"list": [
{
"createTime": 1597030865000,
"delFlag": "0",
"id": 285,
"num": 0,
"questionType": "1",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "B",
"stContent": "多数轿车更换发动机机油的周期里程为________km。",
"stScore": 10,
"stSelecta": "2000--3000",
"stSelectb": "5000--8000",
"stSelectc": "10000--12000",
"stSelectd": "14000--16000",
"stType": "1"
},
{
"createTime": 1597030865000,
"delFlag": "0",
"id": 286,
"num": 0,
"questionType": "1",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "B",
"stContent": "关于镶套修理法,下面说法不正确的是( )",
"stScore": 10,
"stSelecta": "镶套后改变了零件的尺寸",
"stSelectb": "镶套材料应尽量与基体一致",
"stSelectc": "镶套采用了过盈配合",
"stSelectd": "配合表面要求加工精度较高",
"stType": "1"
},
{
"createTime": 1608101282000,
"delFlag": "0",
"id": 452,
"num": 0,
"questionType": "3",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "无",
"stAnswer": "A,B,C",
"stContent": "对磁盘与驱动器中,叙述正确的有",
"stCteater": "1",
"stScore": 10,
"stSelecta": "密度",
"stSelectb": "扇区",
"stSelectc": "磁道",
"stSelectd": "光标本",
"stSelecte": "孔口",
"stSelectf": "",
"stType": "1"
},
{
"createTime": 1608099445000,
"delFlag": "0",
"id": 443,
"num": 0,
"questionType": "3",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "无",
"stAnswer": "A,C,B",
"stContent": "计算机的主要特点是",
"stCteater": "1",
"stScore": 10,
"stSelecta": "运算速度快",
"stSelectb": "精度高",
"stSelectc": "存储记忆",
"stSelectd": "自动编程",
"stSelecte": "用十进制计数",
"stSelectf": "",
"stType": "1"
},
{
"createTime": 1606957884000,
"delFlag": "0",
"id": 372,
"num": 0,
"questionType": "2",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "错",
"stContent": "int是引用数据类型",
"stScore": 10,
"stSelecta": "对",
"stSelectb": "错",
"stType": "1"
},
{
"createTime": 1606957884000,
"delFlag": "0",
"id": 373,
"num": 0,
"questionType": "2",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "错",
"stContent": "string是引用数据类型",
"stScore": 10,
"stSelecta": "对",
"stSelectb": "错",
"stType": "1"
},
{
"createTime": 1606957884000,
"delFlag": "0",
"id": 376,
"num": 0,
"questionType": "4",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "数组和链表的区别",
"stContent": "ArrayList和LinkedList的区别",
"stScore": 10,
"stType": "1"
},
{
"createTime": 1545893669000,
"delFlag": "0",
"id": 44,
"num": 0,
"questionType": "4",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "数组和链表的区别",
"stContent": "1ArrayList和LinkedList的区别",
"stScore": 10,
"stSelecta": "",
"stSelectb": "",
"stSelectc": "",
"stSelectd": "",
"stType": "3"
}
]
},
"code": "200",
"message": "成功"
}
方法一
页面
1.html
{{ iow.sjIntroduction }}
data{
return{
ruleForm: {
resource: [],
},
}
}
第{{ index + 1 }}题:{{ item.stContent
}}({{ item.stScore }}分)
(单选)
(判断)
(多选)
(简答)
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelectc }}
{{ item.stSelectd }}
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelectc }}
{{ item.stSelectd }}
{{ item.stSelecte }}
item.stSelectf }} -->
提交
暂无试题
{{ score }}分
返回
我的测评
2.js - 答题部分
//数据定义
data() {
return {
score: 0, //表单提交后,后端返回的总分
id: '', //获取路由的 query,试卷的id
iow: '', //返回的题目信息
dialogVisible: false, //弹窗
djStarttime: '', //获取当前时间
question: [], //保存后端返回题的数组,页面上需要用它来循环显示每一道题
ruleForm: {
resource: [], //每一道题的值
},
DSQ: null, //定时器,到时间自动提交
DSQTime: 0, //后端返回的结束时间
questionArrText: [], //答题保存的数组
}
},
逻辑
created() {
var djStarttime = new Date()
var year = djStarttime.getFullYear()
var month = (djStarttime.getMonth() + 1).toString()
var day = djStarttime.getDate().toString()
var hour = djStarttime.getHours().toString()
var minute = djStarttime.getMinutes().toString()
var second = djStarttime.getSeconds().toString()
if (month.length == 1) {
month = '0' + month
}
if (day.length == 1) {
day = '0' + day
}
if (hour.length == 1) {
hour = '0' + hour
}
if (minute.length == 1) {
minute = '0' + minute
}
if (second.length == 1) {
second = '0' + second
}
this.djStarttime =
year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second
this.id = this.$route.query.id
//获取当前系统时间,传给后端,用来判断他用了多长时间
//console.log(this.dateTime)
this.init() //初始化函数
},
//监听定时器,如果 当前系统时间的秒值等于或大于后端给定的时间,那么就自动提交题目
watch: {
DSQTime: function (val, oldVal) {
console.log(this.DSQTime)
console.log(this.DSQEndTime)
if (this.DSQTime == this.DSQEndTime) {
clearInterval(this.DSQ)
this.submitForm('ruleForm', true)
}
},
},
methods: {
//给多选框用,否则会出现一个bug,就是先点一下多选框,然后没反应,
//然后点一下按钮或者点击下拉框后,这个多选框就高亮了
change(e) {
this.$forceUpdate()
},
//关闭弹窗函数
handleClose(done) {
this.dialogVisible = false
},
//跳页面的函数
go() {
this.$router.push({ path: '/ME' })
},
//返回上一页
back() {
this.$router.go(-1)
},
//初始化函数
init() {
//定时器,获取当前系统时间(毫秒),然后转化为秒
this.DSQ = setInterval(() => {
this.DSQTime = parseInt(Date.now() / 1000)
}, 1000)
//封装的接口,把试卷id传进去,返回所有题
msgApi
.questionsList(this.id)
.then((res) => {
if (res.data.code == 200) {
this.question = res.data.returnObject.list //页面循环的题
for (let i = 0; i
this.ruleForm.resource[i] = []
}else{
this.ruleForm.resource[i] = ''
}
}
this.questionArrText = res.data.returnObject.list //重新赋值,用来判断他是否全部答完
this.iow = res.data.returnObject.name //题的名字
this.DSQEndTime = parseInt(this.iow.endTime / 1000) //后端返回的时间(毫秒)转化为秒
}
})
.catch((err) => {})
},
//提交函数
//ifs 判断是否是用户自己点击的提交按钮,如果不是,那么就是到时间了,系统自动提交的
submitForm(formName, ifs) {
if (ifs) {
//系统自动提交的话
var arr = [] //最后给后端的是一个json串
var that = this
var b = this.ruleForm.resource.notempty()
//获取他已经答过的题
for (var i = 0; i } //最后给后端的是一个json串
json.id = that.questionArrText[i].id //json的id:题id
//如果是数组(也就是多选题),那么就用join把他换为字符串
if (that.ruleForm.resource[i] instanceof Array) {
json.text = that.ruleForm.resource[i].join()
} else {
json.text = that.ruleForm.resource[i]
}
if (json.text == undefined) { //如果这个题没答,那么就把他重置为空串,而不是给后端一个 undefined 字符串
json.text = ''
}
json.isJD = this.questionArrText[i].questionType //给后端题的类型
arr.push(json) //一个一个push进去
}
var obj = { //传的采纳数
djPaperid: this.id,
djStarttime: this.djStarttime,
djAnswers: JSON.stringify(arr),
}
msgApi
.answers(obj) //请求的接口
.then((res) => {
if (res.data.code == 200) {
//console.log(res)
this.dialogVisible = true
this.score = res.data.returnObject
}
})
.catch((err) => {})
} else {
this.$refs[formName].validate((valid) => { //如果是用户自己点的
if (valid) {
var arr = []
var that = this
var b = this.ruleForm.resource.notempty()
if (b.length !== this.questionArrText.length) {
//要是有未答的题目走if
this.$confirm(
'检测到您有未答完的题目,,是否确认提交试卷?',
'确认信息',
{
distinguishCancelAndClose: true,
confirmButtonText: '确认',
cancelButtonText: '取消',
}
)
.then(() => {
//逻辑和刚刚的一样,
for (var i = 0; i }
json.id = that.questionArrText[i].id
if (that.ruleForm.resource[i] instanceof Array) {
json.text = that.ruleForm.resource[i].join()
} else {
json.text = that.ruleForm.resource[i]
}
if (json.text == undefined) {
json.text = ''
}
json.isJD = this.questionArrText[i].questionType
arr.push(json)
}
var obj = {
djPaperid: this.id,
djStarttime: this.djStarttime,
djAnswers: JSON.stringify(arr),
}
msgApi
.answers(obj)
.then((res) => {
if (res.data.code == 200) {
//console.log(res)
this.dialogVisible = true
this.score = res.data.returnObject
}
})
.catch((err) => {})
})
.catch((action) => {})
} else {
//如果都答了,就走else (其实这个感觉没必要,不过就这吧)
for (var i = 0; i }
json.id = that.questionArrText[i].id
if (that.ruleForm.resource[i] instanceof Array) {
json.text = that.ruleForm.resource[i].join()
} else {
json.text = that.ruleForm.resource[i]
}
json.isJD = this.questionArrText[i].questionType
arr.push(json)
}
var obj = {
djPaperid: this.id,
djStarttime: this.djStarttime,
djAnswers: JSON.stringify(arr),
}
msgApi
.answers(obj)
.then((res) => {
if (res.data.code == 200) {
//console.log(res)
this.dialogVisible = true
this.score = res.data.returnObject
// this.$message.success(res.data.returnObject)
}
})
.catch((err) => {})
}
} else {
//console.log('error submit!!')
return false
}
})
}
},
resetForm(formName) {
this.$refs[formName].resetFields()
},
},
3.js - 回显部分
题目方面和之前的html一样,就是多了个disabled属性,
然后让后端把你给后端的json串拿到手之后,你再去获取到,做一个回显(后端工具人上线)
就发题目部分吧,其他的没什么用
第{{ index + 1 }}题:{{ item.stContent
}}({{ item.stScore }}分)
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelectc }}
{{ item.stSelectd }}
正确答案:{{ item.stAnswer }}
考生答案:
{{ ruleForm.resource[index].text }}
{{ item.stSelecta }}
{{ item.stSelectb }}
正确答案:{{ item.stAnswer }}
考生答案:
{{ ruleForm.resource[index].text }}
{{
item.stSelecta
}}
{{
item.stSelectb
}}
{{
item.stSelectc
}}
{{
item.stSelectd
}}
{{
item.stSelecte
}}
正确答案:{{ item.stAnswer }}
考生答案:
{{ ruleForm.resource[index].text }}
正确答案:{{ item.stAnswer }}
考生答案:
{{ ruleForm.resource[index].text }}
data() { //data还是这个
return {
score: 0,
id: '',
dialogVisible: false,
djStarttime: '',
question: [],
ruleForm: {
resource: [],
},
iow: '',
allanswer: [],
questionArr: [],
rules: {
resource: [
// { required: true, message: '请输入活动名称', trigger: 'blur' }
],
},
}
},
//init 函数有点不一样,先请求题目接口,然后请求答案接口
init() {
//题目接口
msgApi
.questionsList_look(this.id)
.then((res) => {
if (res.data.code == 200) {
this.question = res.data.returnObject.list
for (let i = 0; i })
msgApi
.MyAnswer(this.id)
.then((res) => {
if (res.data.code == 200) {
//console.log(res.data.returnObject)
this.allanswer = res.data.returnObject
this.answer = res.data.returnObject.contArray
console.log(this.answer)
this.ruleForm.resource = this.answer
}
})
.catch((err) => {})
},
方法二:
ps :就是在后端返回题的时候,直接在返回的数据中创建一个保存答案的键值对,然后页面在v-model的时候,把这个创建的值再加上去就行了,止于表单验证什么的…估计得动态加了
1.html
{{ iow.sjIntroduction }}
第{{ index + 1 }}题:{{ item.stContent
}}({{ item.stScore }}分)
(单选)
(判断)
(多选)
(简答)
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelectc }}
{{ item.stSelectd }}
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelecta }}
{{ item.stSelectb }}
{{ item.stSelectc }}
{{ item.stSelectd }}
{{ item.stSelecte }}
item.stSelectf }} -->
提交
暂无试题
2.js - 答题部分
//数据定义
data() {
return {
question: [], //保存后端返回题的数组,页面上需要用它来循环显示每一道题
}
},
逻辑
created() {
this.init() //初始化函数
},
methods: {
//给多选框用,否则会出现一个bug,就是先点一下多选框,然后没反应,
//然后点一下按钮或者点击下拉框后,这个多选框就高亮了
//初始化函数
init() {
msgApi
.questionsList(this.id)
.then((res) => {
if (res.data.code == 200) {
var json = res.data.returnObject.list
for (let i = 0; i
json[i].resource = []
//直接给每一项加一个resource属性,因为res.data他是一个对象,所以可以任意给他添加新的键值对
}else{
json[i].resource = ''
}
}
}
this.question = json //页面循环的题
})
.catch((err) => {})
},
3.js - 回显部分
后端也是会给你返回这样的数据
{
"returnObject": {
"count": 380,
"list": [
{
"createTime": 1597030865000,
"delFlag": "0",
"id": 285,
"num": 0,
"questionType": "1",
"sjIntroduction": "计算机基本知识",
"stAnalysis": "JEIIXJIEJXIJIEXIJEIX",
"stAnswer": "B",
"stContent": "多数轿车更换发动机机油的周期里程为________km。",
"stScore": 10,
"stSelecta": "2000--3000",
"stSelectb": "5000--8000",
"stSelectc": "10000--12000",
"stSelectd": "14000--16000",
"stType": "1"
"用户选择的答案": "A" //会给你个这个字段
}
]
},
"code": "200",
"message": "成功"
}
就是多了一个字段,然后你再把这个字段赋值给item.resource 即可
总结
其他不难,难的是如何使用v-model绑定数据,然后如何让他点哪个哪个高亮
方法一优点:可以使用表单的任何属性,使用方便
方法一缺点:数据结构有点麻烦,然后提交函数最好封装一下
方法二优点:没有报错,不用搞那么多乱七八糟的函数,看着省心,用着及其方便
方法二缺点:表单验证什么的…你懂得
|